﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Linq;

namespace HZY.Framework.Dict.SourceGenerator
{

    [Generator]
    public class DictSourceGenerator : ISourceGenerator
    {
        public DictSourceGenerator()
        {

        }

        public void Execute(GeneratorExecutionContext context)
        {
            List<CodeInfo> codeInfos = new List<CodeInfo>();
            //Debugger.Launch();

            //throw new NotImplementedException();
            // Find the main method
            var mainMethod = context.Compilation.GetEntryPoint(context.CancellationToken);

            foreach (var item in context.Compilation.SyntaxTrees)
            {
                var root = item.GetRoot();
                var descendantNodes = root.DescendantNodes();
                var compilationUnitRoot = item.GetCompilationUnitRoot();

                // 查找 类
                var classDeclarationSyntax = descendantNodes.OfType<ClassDeclarationSyntax>().FirstOrDefault();
                if (classDeclarationSyntax == null)
                {
                    continue;
                }
                // 获取 类 名称
                var className = classDeclarationSyntax.Identifier.Text;

                // 查找 类 usings
                //var usingDirectiveSyntax = descendantNodes.OfType<UsingDirectiveSyntax>();
                //var usingStatementSyntax = descendantNodes.OfType<UsingStatementSyntax>();
                var usings = compilationUnitRoot.Usings;
                var usingsString = string.Join("\r\n", usings);

                var namespaceDeclarationSyntax = descendantNodes.OfType<NamespaceDeclarationSyntax>().FirstOrDefault();
                // 查找 类 命名空间
                var fileScopedNamespaceDeclarationSyntax = descendantNodes.OfType<FileScopedNamespaceDeclarationSyntax>().FirstOrDefault();
                if (namespaceDeclarationSyntax == null && fileScopedNamespaceDeclarationSyntax == null)
                {
                    continue;
                }
                var namespaceString = fileScopedNamespaceDeclarationSyntax?.Name?.ToString() ?? namespaceDeclarationSyntax?.Name?.ToString();

                // 查找 类 属性
                var propertyDeclarationSyntaxList = descendantNodes.OfType<PropertyDeclarationSyntax>().ToList();
                foreach (var nodeItem in propertyDeclarationSyntaxList)
                {
                    // 属性带有的特性
                    var attributeLists = nodeItem.AttributeLists.ToList();

                    // 属性名称
                    var propertyName = nodeItem.Identifier.Text;

                    //var a = (PredefinedTypeSyntax)nodeItem.Type;
                    var isDict = false;
                    foreach (var item1 in attributeLists)
                    {
                        if (!item1.Attributes.Any(s => s.Name.ToString() == "Dict"))
                        {
                            continue;
                        }
                        isDict = true;
                    }

                    if (isDict)
                    {
                        codeInfos.Add(new CodeInfo(usingsString, namespaceString, className, propertyName));
                    }
                }
            }

            var codeInfo = codeInfos.FirstOrDefault();
            if (codeInfo == null) return;

            List<string> fields = new List<string>();
            foreach (var item in codeInfos)
            {
                fields.Add($@"
        /// <summary>
        /// {item.PropertyName} 外键显示文本字段
        /// <para>作用于外键id 生成的显示文本字段</para>
        /// </summary>
        [System.ComponentModel.DataAnnotations.Schema.NotMapped]
        public string {item.GetExtendPropertyName()} {{ get; set; }} ");
            }

            string code = $@"/// =========== 由 SourceGenerator 技术生成 ========= 此类是在字段带有 [Dict(...)] 特性时生成
/// author : hzy

{codeInfo.Usings}

namespace {codeInfo?.Namespace} 
{{

    public partial class {codeInfo?.ClassName}
    {{

{string.Join("\r\n", fields)}

    }}

}}
";
            context.AddSource($"{codeInfo.ClassName}.g.cs", code.ToString());
        }

        public void Initialize(GeneratorInitializationContext context)
        {
            //throw new NotImplementedException();
        }
    }

    public class CodeInfo
    {
        public CodeInfo(string usings, string _namespace, string className, string propertyName)
        {
            Usings = usings;
            Namespace = _namespace;
            ClassName = className;
            PropertyName = propertyName;
        }

        /// <summary>
        /// 引用
        /// </summary>
        public string Usings { get; set; }

        /// <summary>
        /// 命名空间
        /// </summary>
        public string Namespace { get; set; }

        /// <summary>
        /// 类名称
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 属性
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 获取扩展属性名称
        /// </summary>
        /// <returns></returns>
        public string GetExtendPropertyName()
        {
            return PropertyName + "DictText";
        }
    }


}
